import {
    ADD_TODO, DELETE_TODO, EDIT_TODO,
    COMPLETE_TODO, COMPLETE_ALL, CLEAR_COMPLETED,
} from '../constants/ActionTypes';

const initialState = [
    {
        text: 'Use Redux',
        completed: false,
        id: 0,
    },
];

export default function todos(state = initialState, action) {
    switch (action.type) {
        case ADD_TODO:
            return [
                {
                    id: state.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1,
                    completed: false,
                    text: action.text,
                },
                ...state,
            ];

        case DELETE_TODO:
            // filter()方法使用指定的函数测试所有元素，并创建一个包含所有通过测试的元素的新数组。
            // array.filter(callback[, thisArg])
            // callback：用来测试数组的每个元素的函数，包含三个参数。返回true表示保留该元素（通过测试），返回false则不保留。
            //      currentValue：数组中当前被传递的元素。
            //      index：元素的索引。
            //      array：被遍历的数组。
            // thisArg：可选。执行callback时使用的this值。
            return state.filter(todo =>
                todo.id !== action.id
            );

        case EDIT_TODO:
            // map()的参数是个箭头函数。该箭头函数的第一个参数是todo，返回值是一个使用三元运算符的表达式，用于返回新元素。
            // 如果id匹配，则通过Object.assign()合并一个新的属性，也就是给todo添加或者重写一个text属性，
            // 属性值为action.text。

            // 段代码的作用是为数组中指定的任务更新text属性
            return state.map(todo => (
                todo.id === action.id ?
                    Object.assign({}, todo, { text: action.text }) :
                    todo
            ));

        case COMPLETE_TODO:
            return state.map(todo => (
                todo.id === action.id ?
                    Object.assign({}, todo, { completed: !todo.completed }) :
                    todo
            ));

        case COMPLETE_ALL: {
            // every() 方法用于测试数组中所有元素是否都通过了指定函数的测试。
            // array.every(callback[, thisArg])
            // callback：用来测试每个元素的函数。
            //      currentValue：数组中当前被传递的元素。
            //      index：元素的索引。
            //      array：被遍历的数组。
            // thisArg：可选。执行callback时使用的this值。

            // 遍历任务数组，每一项任务的completed属性均为true时候，返回true。
            const areAllMarked = state.every(todo => todo.completed);
            return state.map(todo => Object.assign({}, todo, {
                completed: !areAllMarked,
            }));
        }

        case CLEAR_COMPLETED:
            return state.filter(todo => todo.completed === false);

        default:
            return state;
    }
}
